﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Xunit;

namespace Serious.SweetConfig.Tests
{
    public class ParameterisedXmlTest
    {
		[Fact]
		public void Transform_WithNullParameterList_ThrowsArgumentNullException()
		{
			var exception = Assert.Throws<ArgumentNullException>(
			delegate
			{
				new ParameterisedXml(new XDocument()).Transform(null);
			});

			Assert.Equal("parameters", exception.ParamName);
		}

		[Fact]
		public void Transform_ReplacesMatchedAttributeWithValue()
		{
			var parameterList = new ParameterList()
			{
				new Parameter() { 
					Name="Attribute Test", 
					Match="/configuration/appSettings/add[@key='some.configpath']/@value", 
					Value=@"c:\path\" 
				}
			};

			XDocument actual = new ParameterisedXml(GetTestDocConfig()).Transform(parameterList);

			Assert.Equal((string)actual.Descendants("add")
				.Single(e => e.Attribute("key").Value == "some.configpath").Attribute("value"), 
				@"c:\path\");
		}

		[Fact]
		public void Transform_ReplacesMatchedElementWithValue()
		{
			var parameterList = new ParameterList()
			{
				new Parameter() { 
					Name="Attribute Test", 
					Match="/configuration/appSettings/add[@key='some.configpath']", 
					Value="<add key=\"different\" value=\"\"/>"
				}
			};

			XDocument actual = new ParameterisedXml(GetTestDocConfig()).Transform(parameterList);

			Assert.Equal((string)actual.Descendants("add")
				.Single(e => e.Attribute("key").Value == "different").Attribute("value").Value, "");
			Assert.Null(actual.Descendants("add").SingleOrDefault(e => e.Attribute("key").Value == "some.configpath"));
		}

		[Fact]
		public void Transform_WithEmptyParameterList_ReturnsCopyOfInputXml()
		{
			XDocument inputXml = GetTestDocConfig();
			XDocument actual = new ParameterisedXml(inputXml).Transform(new ParameterList());

			Assert.NotEqual(inputXml, actual);
			Assert.Equal(inputXml.ToString(), actual.ToString());
		}

		[Fact]
		public void Transform_WithNoMatchingParameters_ReturnsCopyOfInputXml()
		{
			var parameters = new ParameterList() { 
				new Parameter() { 
					Value = "aaa", 
					Match = "/configuration/appSettings/add[@key='other.configpath']/@value" 
				} 
			};

			XDocument inputXml = GetTestDocConfig();
			XDocument actual = new ParameterisedXml(inputXml).Transform(parameters);

			Assert.NotEqual(inputXml, actual);
			Assert.Equal(inputXml.ToString(), actual.ToString());
		}

		private XDocument GetTestDocConfig()
		{
			return new XDocument(
				new XElement("configuration", 
					new XElement("appSettings",
						new XElement("add", new XAttribute("key", "some.configpath"), new XAttribute("value", @"d:\path\"))
					)	
				)
			);
		}
    }
}
